﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using TSTreeThesis.Utilities;
using TSTreeThesis.DataMgr;
using DevExpress.XtraTab;
using DevExpress.XtraTab.ViewInfo;
using ZedGraph;
using MPlusTree;
using RStarTree;
using TSTree;
using System.IO;
using TSTreeSAX;

namespace TSTreeThesis.UI
{
    public partial class MainForm : Form
    {
        private IndexMgr indexMgr;
        private double[] query;

        #region Init
        public MainForm()
        {
            InitializeComponent();
            indexMgr = null;
            query = null;

        }

        private WelcomeForm frmWelcome = null;
        private void MainForm_Load(object sender, EventArgs e)
        {
            barEditDataLength.EditValue = Convert.ToString(Utility.DATA_LENGHT);
            barEditCompressRatio.EditValue = Convert.ToString(Utility.COMPRESSION_RATE);
            barEditRadius.EditValue = Convert.ToString(Utility.THRESHOLD_ERROR);
            barEditWindowSize.EditValue = Convert.ToString(Utility.SLIDING_WINDOW_SIZE_ORIGINAL);
            barEditItemSAX.EditValue = Convert.ToString(Utility.SYMBOLS_LENGTH_DEFAULT);

            barCheckSAX.Checked = Utility.QUANTIZATION == 1 ? true : false;
            barEditItemSAX.Enabled = Utility.QUANTIZATION == 1 ? true : false;
            barEditItemMax.Enabled = Utility.QUANTIZATION == 1 ? true : false;
            barEditItemMin.Enabled = Utility.QUANTIZATION == 1 ? true : false;

            barEditItemMax.EditValue = Convert.ToString(Utility.MAXVALUE);
            barEditItemMin.EditValue = Convert.ToString(Utility.MINVALUE);

            if (frmWelcome == null)
                frmWelcome = new WelcomeForm();
            AddTab(frmWelcome, frmWelcome.GetPanel(), Properties.Resources.welcome_16x16);
        }

        private void AddTab(Form newChild, Panel panel)
        {
            XtraTabPage childTab = new XtraTabPage();        //create new tab page
            newChild.MdiParent = this;                       //set as child of this form
            childTab.Name = newChild.Name;                   //make sure name and text are same
            childTab.Text = newChild.Text;                   //this is for syncrhonize later
            xtraTabControl.TabPages.Add(childTab);           //add new tab
            panel.Parent = childTab;                         //attach to tab
            xtraTabControl.SelectedTabPage = childTab;       //this is to make sure that tab page is selected in the same time
            newChild.Show();                                 //as new form created so that corresponding tab and child form is active
        }

        private void AddTab(Form newChild, Panel panel, Image icon)
        {
            XtraTabPage childTab = new XtraTabPage { Image = icon };//create new tab page
            newChild.MdiParent = this;                              //set as child of this form
            childTab.Name = newChild.Name;                          //make sure name and text are same
            childTab.Text = newChild.Text;                          //this is for syncrhonize later
            xtraTabControl.TabPages.Add(childTab);                  //add new tab
            panel.Parent = childTab;                                //attach to tab
            xtraTabControl.SelectedTabPage = childTab;              //this is to make sure that tab page is selected in the same time
            newChild.Show();                                        //as new form created so that corresponding tab and child form is active
        }
        #endregion

        #region Load data & control tab

        public void AddInfo(string Indexname, int noOfData, int noOfInternalNode, int noOfDataNode)
        {
            //listBox_info.Items.Clear();
            listBox_info.Items.Add(Indexname);
            listBox_info.Items.Add(noOfData.ToString() + " Data");
            listBox_info.Items.Add(noOfInternalNode.ToString() + " Internal Node");
            listBox_info.Items.Add(noOfDataNode.ToString() + " Data Node");
            //listBox_info.Items.Add(IOs.ToString() + " IOs");
            //listBox_info.Items.Add(pagesAccess.ToString() + " pages access");
        }
        public void btnLoadData()
        {
            if (Utility.SLIDING_WINDOW_SIZE_ORIGINAL < Utility.COMPRESSION_RATE)
            {
                MessageBox.Show("'Window size' must be greater than or equal 'Compression ratio'!");
                return;
            }
            else
            {
                if (Utility.DATA_LENGHT < Utility.SLIDING_WINDOW_SIZE_ORIGINAL)
                {
                    MessageBox.Show("'Data length' must be greater than or equal 'Window size'!");
                    return;
                }
            }


            using (LoadData frmLoadData = new LoadData())
            {
                //Close old indexs
                if (indexMgr != null)
                {
                    if (indexMgr.GetMPTree() != null)
                        indexMgr.GetMPTree().Close();
                    if (!barCheckSAX.Checked) { 
                    if (indexMgr.GetTSTree() != null)
                        indexMgr.GetTSTree().Close();
                    }
                    else
                    {
                        if (indexMgr.GetTSTreeSAX() != null)
                            indexMgr.GetTSTreeSAX().Close();
                    }
                    if (indexMgr.GetRStarTree() != null)
                        indexMgr.GetRStarTree().Close();
                }
                // roi rac hoa
                if (barCheckSAX.Checked) 
                { 
                        frmLoadData.setProperties(barCheckSAX.Checked,Convert.ToInt32(barEditItemMin.EditValue),Convert.ToInt32(barEditItemMax.EditValue),Convert.ToInt32(barEditItemSAX.EditValue));
                }

                if (frmLoadData.ShowDialog() == DialogResult.OK)
                {
                    //Get new indexs
                    indexMgr = frmLoadData.GetIndexMgr();
                    btnDataGraph_ItemClick(null, null);
                    btnPAAGraph_ItemClick(null, null);
                    btnPAAvsData_ItemClick(null, null);
                    DTWgraphChartBtn_ItemClick(null, null);

                    //AddInfo("R* Tree", indexMgr.GetRStarTree().noOfData, indexMgr.GetRStarTree().noOfInternalNode, indexMgr.GetRStarTree().noOfDataNode);
                    //AddInfo("TS Tree", indexMgr.GetTSTree().noOfData, indexMgr.GetTSTree().noOfInternalNode, indexMgr.GetTSTree().noOfDataNode);
                }
            }
        }
      

        private void btn_LoadData_Click(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            btnLoadData();
        }


        private void LoadData_menu_click(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            btnLoadData();
        }


        private DataGraphForm frmDataGraph = null;

        private void btnDataGraph_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            if (frmDataGraph != null && frmDataGraph.Visible == true)
            {
                for (int i = 0; i < xtraTabControl.TabPages.Count; ++i)
                {
                    if (xtraTabControl.TabPages[i].Name == frmDataGraph.Name)
                    {
                        xtraTabControl.SelectedTabPageIndex = i;
                    }
                }
            }
            else
            {
                if (frmDataGraph != null) frmDataGraph.Dispose();
                frmDataGraph = new DataGraphForm();
                AddTab(frmDataGraph, frmDataGraph.GetPanel(), Properties.Resources.chart_file_16x16);
            }

            if (indexMgr != null && indexMgr.GetData() != null)
            {
                PointPairList listOriginal = new PointPairList();
                indexMgr.GetData().getNormalizedDataChart(ref listOriginal);
                frmDataGraph.SetData(listOriginal);
            }
        }

        private DTWGraphForm frmDTWGraph = null;
        private void DTWgraphChartBtn_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            if (frmDTWGraph != null && frmDTWGraph.Visible == true)
            {
                for (int i = 0; i < xtraTabControl.TabPages.Count; ++i)
                {
                    if (xtraTabControl.TabPages[i].Name == frmDTWGraph.Name)
                    {
                        xtraTabControl.SelectedTabPageIndex = i;
                    }
                }
            }
            else
            {
                if (frmDTWGraph != null) frmDTWGraph.Dispose();
                frmDTWGraph = new DTWGraphForm();
                AddTab(frmDTWGraph, frmDTWGraph.GetPanel(), Properties.Resources.ok_16x16);
            }

            if (indexMgr != null && indexMgr.GetData() != null)
            {
                PointPairList listDTW = new PointPairList();
                indexMgr.GetData().getPAAUNormalizedDataChart(ref listDTW);
                PointPairList listDTW2 = new PointPairList();
                indexMgr.GetData().getPAALNormalizedDataChart(ref listDTW2);

                frmDTWGraph.SetData(listDTW, listDTW2);
            }
        }

        private PAAGraphForm frmPAAGraph = null;
        private void btnPAAGraph_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            if (frmPAAGraph != null && frmPAAGraph.Visible == true)
            {
                for (int i = 0; i < xtraTabControl.TabPages.Count; ++i)
                {
                    if (xtraTabControl.TabPages[i].Name == frmPAAGraph.Name)
                    {
                        xtraTabControl.SelectedTabPageIndex = i;
                    }
                }
            }
            else
            {
                if (frmPAAGraph != null) frmPAAGraph.Dispose();
                frmPAAGraph = new PAAGraphForm();
                AddTab(frmPAAGraph, frmPAAGraph.GetPanel(), Properties.Resources.PAA_16x16);
            }

            if (indexMgr != null && indexMgr.GetData() != null)
            {
                PointPairList listPAA = new PointPairList();
                indexMgr.GetData().getPAANormalizedDataChart(ref listPAA);
                frmPAAGraph.SetData(listPAA);
            }
        }


        private PAAvsDataGraphForm frmPAAvsDataGraph = null;

        private void btnPAAvsData_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            if (frmPAAvsDataGraph != null && frmPAAvsDataGraph.Visible == true)
            {
                for (int i = 0; i < xtraTabControl.TabPages.Count; ++i)
                {
                    if (xtraTabControl.TabPages[i].Name == frmPAAvsDataGraph.Name)
                    {
                        xtraTabControl.SelectedTabPageIndex = i;
                    }
                }
            }
            else
            {
                if (frmPAAvsDataGraph != null) frmPAAvsDataGraph.Dispose();
                frmPAAvsDataGraph = new PAAvsDataGraphForm();
                AddTab(frmPAAvsDataGraph, frmPAAvsDataGraph.GetPanel(), Properties.Resources.compare_data_paa_16x16);
            }

            if (indexMgr != null && indexMgr.GetData() != null)
            {
                PointPairList listOriginal = new PointPairList();
                indexMgr.GetData().getNormalizedDataChart(ref listOriginal);
                frmDataGraph.SetData(listOriginal);

                PointPairList listPAA = new PointPairList();
                indexMgr.GetData().getPAANormalizedDataChart(ref listPAA);
                frmPAAGraph.SetData(listPAA);

                frmPAAvsDataGraph.SetData(listOriginal, listPAA);
            }
        }


        public void btn_LoadQuery()
        {
            if (indexMgr != null)
            {
                openFileDialog.Filter = "";
                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    using (LoadQuery frmLoadQuery = new LoadQuery(openFileDialog.FileName, indexMgr.GetMeanValue(), indexMgr.GetStdValue()))
                    {
                        frmLoadQuery.ShowDialog();
                        query = frmLoadQuery.GetQueryArr();
                        zedGraphQuery.GraphPane.CurveList.Clear();
                        addLine(zedGraphQuery, "Query", frmLoadQuery.GetQueryList(), Color.Green, SymbolType.None, 2, "Query Graph");
                    }
                }
            }
            else
            {
                MessageBox.Show("You must load data before query!");
            }
        }

        private void btnLoadQueryMenu_Click(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            btn_LoadQuery();
        }


        private void btn_Loadquery_click(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            btn_LoadQuery();
        }

        private void btn_Loadquery_click2(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            btn_LoadQuery();
        }


        private void addLine(ZedGraphControl zgc, string name, PointPairList dataList, Color color, SymbolType s, int width, string filename)
        {
            GraphPane myPane = zgc.GraphPane;
            LineItem myCurve = myPane.AddCurve(name, dataList, color, s);
            myCurve.Line.Width = width;
            myPane.Title.Text = filename;
            myPane.XAxis.Title.Text = "Times";
            myPane.YAxis.Title.Text = "Values";
            zgc.AxisChange();
            zgc.Refresh();
        }

        private void xtraTabControl_CloseButtonClick(object sender, EventArgs e)
        {
            if (xtraTabControl.SelectedTabPage != null)     //if no child has created, an error will occur
            {
                XtraTabPage page = (XtraTabPage)((ClosePageButtonEventArgs)e).Page;
                int index = -1;
                for (int i = 0; i < xtraTabControl.TabPages.Count; ++i)
                {
                    if (((ClosePageButtonEventArgs)e).Page == xtraTabControl.TabPages[i])
                        index = i;
                }

                //Close the child form
                foreach (Form WantToSelect in this.MdiChildren)
                {
                    if (WantToSelect.Name == page.Name)    //this is why you must make sure child form's and tab page's name are same
                    {                                         //for easier control
                        WantToSelect.Close();
                        WantToSelect.Visible = false;
                        break;
                    }
                }


                page.Dispose();

                //Select an another tab
                if (index > 0)
                    xtraTabControl.SelectedTabPageIndex = index - 1;
                else if (index == 0 && xtraTabControl.TabPages.Count > 0)
                    xtraTabControl.SelectedTabPageIndex = index;

            }  
        }


        private void btnExit_click(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            Application.Exit();
        }


        #endregion

        #region Set configuration
        private void barEditRadius_EditValueChanged(object sender, EventArgs e)
        {
            double value = double.Parse(barEditRadius.EditValue.ToString());
            if (value < 0)
            {
                barEditRadius.EditValue = 0;
                Utility.THRESHOLD_ERROR = 0;
            }
            else
            {
                Utility.THRESHOLD_ERROR = value;
            }
        }

        private void barEditDataLength_EditValueChanged(object sender, EventArgs e)
        {
            Utility.DATA_LENGHT = int.Parse(barEditDataLength.EditValue.ToString());
            if (Utility.DATA_LENGHT <= 0)
            {
                barEditDataLength.EditValue = 1;
            }
        }

        private void barEditWindowSize_EditValueChanged(object sender, EventArgs e)
        {
            Utility.SLIDING_WINDOW_SIZE_ORIGINAL = int.Parse(barEditWindowSize.EditValue.ToString());
            if (Utility.SLIDING_WINDOW_SIZE_ORIGINAL <= 0)
            {
                barEditWindowSize.EditValue = 1;
                return;
            }

            Utility.SLIDING_WINDOW_SIZE = Utility.SLIDING_WINDOW_SIZE_ORIGINAL / Utility.COMPRESSION_RATE;
        }

        private void barEditCompressRatio_EditValueChanged(object sender, EventArgs e)
        {
            Utility.COMPRESSION_RATE = int.Parse(barEditCompressRatio.EditValue.ToString());
            if (Utility.COMPRESSION_RATE <= 0)
            {
                barEditCompressRatio.EditValue = 1;
                return;
            }

            Utility.SLIDING_WINDOW_SIZE = Utility.SLIDING_WINDOW_SIZE_ORIGINAL / Utility.COMPRESSION_RATE;
        }

        #endregion

        #region Run search & show result
        public void AddInfo(string Indexname, int miliseconds, int reads, int writes, int IOs,int dataAccess, int indexAccess, int pagesAccess,int candidates)
        {
            listBox_info.Items.Add(Indexname);
            listBox_info.Items.Add(miliseconds.ToString() + " miliseconds");
            //listBox_info.Items.Add(reads.ToString() + " reads");
            //listBox_info.Items.Add(writes.ToString() + " writes");
            //listBox_info.Items.Add(IOs.ToString() + " IOs");
            listBox_info.Items.Add(indexAccess.ToString() + " index access");
            listBox_info.Items.Add(dataAccess.ToString() + " data access");
            listBox_info.Items.Add(pagesAccess.ToString() + " pages access");
            listBox_info.Items.Add(candidates.ToString() + " candidates");

        }
        private void btnRunQuery_Click(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            if (indexMgr != null)
            {
                if (query != null)
                {
                    if (query.Length == Utility.SLIDING_WINDOW_SIZE * Utility.COMPRESSION_RATE)
                    {
                        if (Utility.THRESHOLD_ERROR == 0) Utility.THRESHOLD_ERROR = 0.01;
                        ArrayList queryResult = null;
                        if (editIndexStructure.EditValue.ToString() == "M+Tree")
                        {
                            if (indexMgr.GetMPTree() == null)
                            {
                                MessageBox.Show("No data loaded!");
                                return;
                            }

                            MPTreeKey q = new MPTreeKey();
                            q.SetData(query);

                            DateTime dt = DateTime.Now;
                            MPStore.IOread = 0;
                            MPStore.IOwrite = 0;
                            Utility.DISTANCE_CALC = 0;

                            queryResult = indexMgr.SearchDataIndex(q, Utility.THRESHOLD_ERROR);
                           // AddInfo("M+ Tree", (int)DateTime.Now.Subtract(dt).TotalMilliseconds, MPStore.IOread, MPStore.IOwrite, MPStore.IOread + MPStore.IOwrite, Utility.DISTANCE_CALC);

                            //MessageBox.Show(String.Format("M+ Tree: {0} miliseconds, {1} reads, {2} writes, {3} IOs, {4} distant calc", DateTime.Now.Subtract(dt).Milliseconds, MPStore.IOread, MPStore.IOwrite, MPStore.IOread + MPStore.IOwrite, Utility.DISTANCE_CALC));
                        }
                        else if (editIndexStructure.EditValue.ToString() == "R*Tree")
                        {
                            if (indexMgr.GetRStarTree() == null)
                            {
                                MessageBox.Show("No data loaded!");
                                return;
                            }

                            PPoint q = new PPoint(query.Length);
                            for (int i = 0; i < query.Length; i++)
                            {
                                q.data[i] = (float)query[i];
                            }

                            DateTime dt = DateTime.Now;
                            BlockFile.IOread = 0;
                            BlockFile.IOwrite = 0;

                            queryResult = indexMgr.SearchDataIndex(q, (float)Utility.THRESHOLD_ERROR);
                            AddInfo("R* Tree", Utility.SEARCH_TIME_RTREE, BlockFile.IOread, BlockFile.IOwrite, BlockFile.IOread + BlockFile.IOwrite, indexMgr.GetRStarTree().data_access, indexMgr.GetRStarTree().index_access, indexMgr.GetRStarTree().page_access, Utility.SEARCH_CANDIDATE_RTREE);
                            //MessageBox.Show(String.Format("R* Tree: {0} miliseconds, {1} IOs, {2} page_access", DateTime.Now.Subtract(dt).Milliseconds, BlockFile.IOread + BlockFile.IOwrite, indexMgr.GetRStarTree().page_access));
                        }
                        else if (editIndexStructure.EditValue.ToString() == "TSTree")
                        {
                            if (!barCheckSAX.Checked) 
                            { 
                                if (indexMgr.GetTSTree() == null)
                                {
                                    MessageBox.Show("No data loaded!");
                                    return;
                                }

                                TSPoint q = new TSPoint(query.Length);
                                for (int i = 0; i < query.Length; i++)
                                {
                                    q.data[i] = (float)query[i];
                                }

                                DateTime dt = DateTime.Now;
                                TSTree.fuctions.BlockFile.IOread = 0;
                                TSTree.fuctions.BlockFile.IOwrite = 0;

                                queryResult = indexMgr.SearchDataIndex(q, (float)Utility.THRESHOLD_ERROR);
                               // AddInfo("TS Tree", (int) DateTime.Now.Subtract(dt).TotalMilliseconds, TSTree.fuctions.BlockFile.IOread, TSTree.fuctions.BlockFile.IOwrite, TSTree.fuctions.BlockFile.IOread + TSTree.fuctions.BlockFile.IOwrite, indexMgr.GetTSTree().page_access);
                                //MessageBox.Show(String.Format("TS Tree: {0} miliseconds, {1} IOs, {2} page_access", DateTime.Now.Subtract(dt).Milliseconds, BlockFile.IOread + BlockFile.IOwrite, indexMgr.GetRStarTree().page_access));
                            }
                            else
                            {
                                if (indexMgr.GetTSTreeSAX() == null)
                                {
                                    MessageBox.Show("No data loaded!");
                                    return;
                                }

                                STSPoint q = new STSPoint(query.Length);
                                for (int i = 0; i < query.Length; i++)
                                {
                                    q.fdata[i] = (float)query[i];
                                }

                                DateTime dt = DateTime.Now;
                                TSTreeSAX.fuctions.BlockFile.IOread = 0;
                                TSTreeSAX.fuctions.BlockFile.IOwrite = 0;

                                queryResult = indexMgr.SearchDataIndex(q, (float)Utility.THRESHOLD_ERROR, Convert.ToInt32(barEditItemSAX.EditValue), Convert.ToInt32(barEditItemMax.EditValue), Convert.ToInt32(barEditItemMin.EditValue));
                                AddInfo("TS SAX Tree", Utility.SEARCH_TIME_TSTREE, TSTreeSAX.fuctions.BlockFile.IOread, TSTreeSAX.fuctions.BlockFile.IOwrite, TSTreeSAX.fuctions.BlockFile.IOread + TSTreeSAX.fuctions.BlockFile.IOwrite,indexMgr.GetTSTreeSAX().data_acess ,indexMgr.GetTSTreeSAX().index_acess, indexMgr.GetTSTreeSAX().page_access, Utility.SEARCH_CANDIDATE_TSTREE);
                               
                            }
                        }

                        ShowQueryResults(queryResult);
                    }
                    else
                    {
                        MessageBox.Show("Invalid number of dimension query!", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
                else
                {
                    MessageBox.Show("No query loaded!", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            else
            {
                MessageBox.Show("No data loaded!", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void clearResultInfo_Click(object sender, EventArgs e)
        {
            listBox_info.Items.Clear();
        }

        private void SortResultByIndex()
        {
            if (arrIndexResult != null)
            {
                int i;
                int j;
                int idx;
                int tmpIndex;
                double tmpDistance;
                for (i = 0; i < arrIndexResult.Length; ++i)
                {
                    idx = i;
                    for (j = i; j < arrIndexResult.Length; ++j)
                    {
                        if (arrIndexResult[idx] > arrIndexResult[j])
                        {
                            idx = j;
                        }
                    }

                    if (idx != i)
                    {
                        tmpIndex = arrIndexResult[i];
                        arrIndexResult[i] = arrIndexResult[idx];
                        arrIndexResult[idx] = tmpIndex;

                        tmpDistance = arrDistResult[i];
                        arrDistResult[i] = arrDistResult[idx];
                        arrDistResult[idx] = tmpDistance;
                    }
                }
            }
        }

        private void SortResultByDistance()
        {
            if (arrDistResult != null)
            {
                int i;
                int j;
                int idx;
                int tmpIndex;
                double tmpDistance;
                for (i = 0; i < arrDistResult.Length; ++i)
                {
                    idx = i;
                    for (j = i; j < arrDistResult.Length; ++j)
                    {
                        if (arrDistResult[idx] > arrDistResult[j])
                        {
                            idx = j;
                        }
                    }

                    if (idx != i)
                    {
                        tmpIndex = arrIndexResult[i];
                        arrIndexResult[i] = arrIndexResult[idx];
                        arrIndexResult[idx] = tmpIndex;

                        tmpDistance = arrDistResult[i];
                        arrDistResult[i] = arrDistResult[idx];
                        arrDistResult[idx] = tmpDistance;
                    }
                }
            }
        }


        private int[] arrIndexResult = null;
        private double[] arrDistResult = null;
        private void ShowQueryResults(ArrayList queryResult)
        {
            if (queryResult != null)
            {
                //Clear old results;
                frmDataGraph.ClearQueryResult();
                listQueryResult.Items.Clear();

                if (queryResult.Count == 0)
                {
                    listQueryResult.Items.Add("The query return no results");
                    return;
                }
                listQueryResult.Items.Add("Query results = " + queryResult.Count);
                int offset = 0;
                frmDataGraph.ClearData();

                arrIndexResult = new int[queryResult.Count];
                arrDistResult = new double[queryResult.Count];
                double[] result;
                for (int i = 0; i < queryResult.Count; i++)
                {
                    int index = (int)queryResult[i] * Utility.COMPRESSION_RATE;

                    if (i > 0 && index < (int)queryResult[i - 1] * Utility.COMPRESSION_RATE + Utility.SLIDING_WINDOW_SIZE_ORIGINAL)
                        offset++;
                    else offset = 0;

                    result = GetResultByIndex(index);
                    frmDataGraph.DrawQueryResult(result, index, offset);
                    arrDistResult[i] = Math.Round(Utility.DTWdistance(query, result), 2);

                    //Console.WriteLine("query lengh 1 :" + query.Length.ToString());
                    //Console.WriteLine("result lengh 1 :" + result.Length.ToString());

                    arrIndexResult[i] = index;
                    listQueryResult.Items.Add("["+ i + "]" + "Index = " + index + ";\t Distance = " + arrDistResult[i]);
                }

                frmDataGraph.ReDrawData();
                frmDataGraph.Refresh();
            }
            else
            {
                MessageBox.Show("Null");
            }
        }

        private double[] GetResultByIndex(int index)
        {
            if (index >= 0 && index < indexMgr.GetData().originalData.Length)
            {
                double[] query = new double[Utility.SLIDING_WINDOW_SIZE_ORIGINAL];
                Array.Copy(indexMgr.GetData().nomalizedData, index, query, 0, Utility.SLIDING_WINDOW_SIZE_ORIGINAL);

                return query;
            }

            return null;
        }

        private QueryResultForm frmResult = null;
        public void SetNullResultFrm()
        {
            frmResult = null;
        }


        private void listQueryResult_DoubleClick(object sender, EventArgs e)
        {
            if (listQueryResult.SelectedItems.Count > 0 && listQueryResult.SelectedIndex > 0)
            {
                PointPairList queryList = new PointPairList();
                PointPairList list = new PointPairList();

                string s = listQueryResult.SelectedItems[0].ToString();
                int startIndex = s.IndexOf("= ") + 2;
                int endIndex = s.LastIndexOf(";");
         
                int index = int.Parse(s.Substring(startIndex,endIndex-startIndex));
                double[] result = GetResultByIndex(index);

                for (int i = 0; i < result.Length; i++)
                {
                    list.Add(i, result[i]);
                    queryList.Add(i, query[i]);
                }

                if (frmResult == null)
                    frmResult = new QueryResultForm(this);

                //Console.WriteLine("query lengh 2 :" + query.Length.ToString());
                //Console.WriteLine("result lengh 2 :" + result.Length.ToString());


                frmResult.SetData(queryList, list, index, Math.Round(Utility.DTWdistance(query, result), 2));
                frmResult.Show();
            }
        }


        private void btnClear_Click(object sender, EventArgs e)
        {
            listQueryResult.Items.Clear();

            if (frmDataGraph != null)
                frmDataGraph.ClearQueryResult();

            arrIndexResult = null;
            arrDistResult = null;
        }

        private void btnSortByDist_click(object sender, EventArgs e)
        {
            if (arrDistResult != null)
            {
                SortResultByDistance();
                listQueryResult.Items.Clear();
                listQueryResult.Items.Add("Query results = " + arrDistResult.Length);
                for (int i = 0; i < arrDistResult.Length; ++i)
                {
                    listQueryResult.Items.Add("[" + i + "]" + "Index = " + arrIndexResult[i] + ";\t Distance = " + arrDistResult[i]);
                }
            }
        }

        private void btnSortByPos_click(object sender, EventArgs e)
        {
            
            if (arrDistResult != null)
            {
                SortResultByIndex();
                listQueryResult.Items.Clear();
                listQueryResult.Items.Add("Query results = " + arrDistResult.Length);
                for (int i = 0; i < arrDistResult.Length; ++i)
                {
                    listQueryResult.Items.Add("[" + i + "]" + "Index = " + arrIndexResult[i] + ";\t Distance = " + arrDistResult[i]);
                }
            }
        }

        #endregion

        #region Open project

        public void OpenProject()
        {
            openFileDialog.Filter = "M, M+, R* (*.conf)|*.conf|All files (*.*)|*.*";
            if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                if (openFileDialog.FileName.Substring(openFileDialog.FileName.LastIndexOf('.') + 1) == "conf")
                {

                    BinaryReader reader = new BinaryReader(new FileStream(openFileDialog.FileName, FileMode.Open));
                    barEditDataLength.EditValue = reader.ReadInt32();
                    barEditWindowSize.EditValue = reader.ReadInt32();
                    barEditCompressRatio.EditValue = reader.ReadInt32();
                    Utility.PAGE_SIZE = reader.ReadInt32();
                    reader.Close();

                    //Read data
                    string dataFile = openFileDialog.FileName.Remove(openFileDialog.FileName.LastIndexOf('.')) + ".txt";

                    if (File.Exists(dataFile))
                    {
                        //Close old indexs
                        if (indexMgr != null)
                        {
                            if (indexMgr.GetMPTree() != null)
                                indexMgr.GetMPTree().Close();
                            //if (indexMgr.GetMTree() != null)
                            //    indexMgr.GetMTree().Close();
                            if (indexMgr.GetRStarTree() != null)
                                indexMgr.GetRStarTree().Close();
                        }

                        indexMgr = new IndexMgr();

                        FileData data = new FileData(dataFile, Utility.COMPRESSION_RATE);
                        data.readData(0, Utility.DATA_LENGHT);
                        data.normalizeData();
                        data.encodeNomalizedData(new PAATransform());

                        indexMgr.SetMeanValue(data.MEAN);
                        indexMgr.SetStdValue(data.STD);

                        //Open R-Tree
                        RTree rtree = null;
                        string rtreeFile = openFileDialog.FileName.Remove(openFileDialog.FileName.LastIndexOf('.')) + ".rtree";
                        if (File.Exists(rtreeFile))
                        {
                            rtree = new RTree(rtreeFile, 256);
                        }
                        else
                        {
                            MessageBox.Show("R* indexing file doesnt't exist");
                        }

                        //Open TS-Tree
                        string tstreeFile = openFileDialog.FileName.Remove(openFileDialog.FileName.LastIndexOf('.')) + ".tstree";
                        TRTree tstreeIndex = null;
                        if (File.Exists(tstreeFile))
                        {
                            tstreeIndex = new TRTree(tstreeFile, 256);
                        }
                        else
                        {
                            MessageBox.Show("M indexing file doesnt't exist");
                        }


                        //Open M+-Tree
                        string mptreeFile = openFileDialog.FileName.Remove(openFileDialog.FileName.LastIndexOf('.')) + ".mptree";
                        MPTree<MPTreeKey> mptree = new MPTree<MPTreeKey>(Utility.PAGE_SIZE);
                        if (File.Exists(mptreeFile))
                        {
                            mptree = new MPTree<MPTreeKey>(Utility.PAGE_SIZE);
                            mptree.OpenTree(mptreeFile);
                        }
                        else
                        {
                            MessageBox.Show("M indexing file doesnt't exist");
                        }


                        indexMgr.SetData(data);
                        indexMgr.SetRStarTree(rtree);
                        indexMgr.SetTSTree(tstreeIndex);
                        indexMgr.SetMPTree(mptree);

                        btnDataGraph_ItemClick(null, null);
                        btnPAAGraph_ItemClick(null, null);
                        btnPAAvsData_ItemClick(null, null);
                        btnDataGraph_ItemClick(null, null);
                    }
                    else
                    {
                        MessageBox.Show("Original data file doesn't exist!");
                    }
                }
                else
                {
                    MessageBox.Show("File name extension is wrong!");
                }
            }
        }

        private void btn_Open_click(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            OpenProject();
        }

        private void btnOpenR_click(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            openFileDialog.Filter = "R (*.rtree)|*.rtree|All files (*.*)|*.*";
            if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                if (openFileDialog.FileName.Substring(openFileDialog.FileName.LastIndexOf('.') + 1) == "rtree")
                {
                    //Read config
                    string configFile = openFileDialog.FileName.Remove(openFileDialog.FileName.LastIndexOf('.')) + ".conf";
                    if (!File.Exists(configFile))
                    {
                        MessageBox.Show(String.Format("The configuration file: '{0}' doesn't exist!\r\nFailed to load R* tree.", configFile), "", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                        return;
                    }
                    BinaryReader reader = new BinaryReader(new FileStream(configFile, FileMode.Open));
                    barEditDataLength.EditValue = reader.ReadInt32();
                    barEditWindowSize.EditValue = reader.ReadInt32();
                    barEditCompressRatio.EditValue = reader.ReadInt32();
                    Utility.PAGE_SIZE = reader.ReadInt32();
                    reader.Close();

                    //Read data
                    string dataFile = openFileDialog.FileName.Remove(openFileDialog.FileName.LastIndexOf('.')) + ".txt";

                    if (File.Exists(dataFile))
                    {
                        //Close old indexs
                        if (indexMgr != null)
                        {
                            if (indexMgr.GetMPTree() != null)
                                indexMgr.GetMPTree().Close();
                            if (indexMgr.GetTSTree() != null)
                                indexMgr.GetTSTree().Close();
                            if (indexMgr.GetRStarTree() != null)
                                indexMgr.GetRStarTree().Close();
                        }

                        indexMgr = new IndexMgr();

                        FileData data = new FileData(dataFile, Utility.COMPRESSION_RATE);
                        data.readData(0, Utility.DATA_LENGHT);
                        data.normalizeData();
                        data.encodeNomalizedData(new PAATransform());

                        indexMgr.SetMeanValue(data.MEAN);
                        indexMgr.SetStdValue(data.STD);
                        RTree rtree = new RTree(openFileDialog.FileName, 256);

                        indexMgr.SetData(data);
                        indexMgr.SetRStarTree(rtree);

                        btnDataGraph_ItemClick(null, null);
                        btnPAAGraph_ItemClick(null, null);
                        btnPAAvsData_ItemClick(null, null);
                        btnDataGraph_ItemClick(null, null);
                    }
                    else
                    {
                        MessageBox.Show("Original data file doesn't exist!");
                    }
                }
                else
                {
                    MessageBox.Show("File name extension is wrong!");
                }
            }
        }


        private void btnOpenMP_click(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            openFileDialog.Filter = "M+ (*.mptree)|*.mptree|All files (*.*)|*.*";
            if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                if (openFileDialog.FileName.Substring(openFileDialog.FileName.LastIndexOf('.') + 1) == "mptree")
                {
                    //Read config
                    string configFile = openFileDialog.FileName.Remove(openFileDialog.FileName.LastIndexOf('.')) + ".conf";

                    if (!File.Exists(configFile))
                    {
                        MessageBox.Show(String.Format("The configuration file: '{0}' doesn't exist!\r\nFailed to load M+ tree.", configFile), "", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                        return;
                    }

                    BinaryReader reader = new BinaryReader(new FileStream(configFile, FileMode.Open));
                    barEditDataLength.EditValue = reader.ReadInt32();
                    barEditWindowSize.EditValue = reader.ReadInt32();
                    barEditCompressRatio.EditValue = reader.ReadInt32();
                    Utility.PAGE_SIZE = reader.ReadInt32();
                    reader.Close();

                    //read data
                    string dataFile = openFileDialog.FileName.Remove(openFileDialog.FileName.LastIndexOf('.')) + ".txt";

                    if (File.Exists(dataFile))
                    {
                        //Close old indexs
                        if (indexMgr != null)
                        {
                            if (indexMgr.GetMPTree() != null)
                                indexMgr.GetMPTree().Close();
                            if (indexMgr.GetTSTree() != null)
                                indexMgr.GetTSTree().Close();
                            if (indexMgr.GetRStarTree() != null)
                                indexMgr.GetRStarTree().Close();
                        }

                        indexMgr = new IndexMgr();

                        FileData data = new FileData(dataFile, Utility.COMPRESSION_RATE);
                        data.readData(0, Utility.DATA_LENGHT);
                        data.normalizeData();
                        data.encodeNomalizedData(new PAATransform());

                        indexMgr.SetMeanValue(data.MEAN);
                        indexMgr.SetStdValue(data.STD);
                        MPTree<MPTreeKey> mptree = new MPTree<MPTreeKey>(Utility.PAGE_SIZE);
                        mptree.OpenTree(openFileDialog.FileName);

                        indexMgr.SetData(data);
                        indexMgr.SetMPTree(mptree);

                        btnDataGraph_ItemClick(null, null);
                        btnPAAGraph_ItemClick(null, null);
                        btnPAAvsData_ItemClick(null, null);
                        btnDataGraph_ItemClick(null, null);
                    }
                    else
                    {
                        MessageBox.Show("Original data file doesn't exist!");
                    }
                }
                else
                {
                    MessageBox.Show("File name extension is wrong!");
                }
            }
        }

        #endregion

        #region SAX
        private void barCheckSAX_Changed(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            if (barCheckSAX.Checked)
            {
                barEditItemSAX.Enabled = true;
                barEditItemMax.Enabled = true;
                barEditItemMin.Enabled = true;
            }
            else
            {
                barEditItemSAX.Enabled = false;
                barEditItemMax.Enabled = false;
                barEditItemMin.Enabled = false;
            }

        }

       
        #endregion

        #region Show experiment
        private void EntriesPerNode_click(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            float avgRTreePerInternalNode = 0;
            float avgRTreePerLeafNode = 0;
            float avfTSTreePerInternalNode = 0;
            float avgTSTreePerLeafNode = 0;

            if (indexMgr == null) { MessageBox.Show("Please load data !"); return; }

            if (indexMgr.GetRStarTree() != null)
            {
                avgRTreePerInternalNode = indexMgr.getRtreeEntriesPerNode(Utility.NOOF_ENTRIES_PER_INTERNAL_NODE);
                avgRTreePerLeafNode = indexMgr.getRtreeEntriesPerNode(Utility.NOOF_ENTRIES_PER_LEAF_NODE);
            }
            else
            {
                MessageBox.Show("R-tree is null ! ");
                return;
            }
            if (barCheckSAX.Checked)
            {
                if (indexMgr.GetTSTreeSAX() != null) 
                { 
                     avfTSTreePerInternalNode = indexMgr.getTStreeEntriesPerNode(Utility.NOOF_ENTRIES_PER_INTERNAL_NODE,barCheckSAX.Checked);
                     avgTSTreePerLeafNode = indexMgr.getTStreeEntriesPerNode(Utility.NOOF_ENTRIES_PER_LEAF_NODE, barCheckSAX.Checked);
                }
                else
                {
                    MessageBox.Show("TSSAX-tree is null ! ");
                    return;
                }
            }
            else
            {
                if (indexMgr.GetTSTree() != null)
                {
                    avfTSTreePerInternalNode = indexMgr.getTStreeEntriesPerNode(Utility.NOOF_ENTRIES_PER_INTERNAL_NODE, barCheckSAX.Checked);
                    avgTSTreePerLeafNode = indexMgr.getTStreeEntriesPerNode(Utility.NOOF_ENTRIES_PER_LEAF_NODE, barCheckSAX.Checked);
                }
                else
                {
                    MessageBox.Show("TS-tree is null ! ");
                    return;
                }
            }
            string str = string.Format("R-Tree : \nNon-leaf:{0}\nLeaf:{1}\nTS-Tree:\nNon-leaf:{2}\nLeaf:{3}", avgRTreePerInternalNode, avgRTreePerLeafNode, avfTSTreePerInternalNode, avgTSTreePerLeafNode);
            MessageBox.Show(str);
        }

        private void barButtonCompactness_click(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            int RTreeNodelevel1 = 0;
            int RTreeNodelevel2 = 0;
            int RTreeNodelevel3 = 0;

            int TSTreeNodelevel1 = 0;
            int TSTreeNodelevel2 = 0;
            int TSTreeNodelevel3 = 0;

            if (indexMgr == null) { MessageBox.Show("Please load data !"); return; }

            if (indexMgr.GetRStarTree() != null)
            {
                RTreeNodelevel1 = indexMgr.getRtreeNodeByLevel(1);
                RTreeNodelevel2 = indexMgr.getRtreeNodeByLevel(2);
                RTreeNodelevel3 = indexMgr.getRtreeNodeByLevel(3);
            }
            else
            {
                MessageBox.Show("R-tree is null ! ");
                return;
            }
            if (barCheckSAX.Checked)
            {
                if (indexMgr.GetTSTreeSAX() != null)
                {
                    TSTreeNodelevel1 = indexMgr.getTStreeNodeByLevel(1, barCheckSAX.Checked);
                    TSTreeNodelevel2 = indexMgr.getTStreeNodeByLevel(2, barCheckSAX.Checked);
                    TSTreeNodelevel3 = indexMgr.getTStreeNodeByLevel(3, barCheckSAX.Checked);
                }
                else
                {
                    MessageBox.Show("TSSAX-tree is null ! ");
                    return;
                }
            }
            else
            {
                if (indexMgr.GetTSTree() != null)
                {
                    TSTreeNodelevel1 = indexMgr.getTStreeNodeByLevel(1, barCheckSAX.Checked);
                    TSTreeNodelevel2 = indexMgr.getTStreeNodeByLevel(2, barCheckSAX.Checked);
                    TSTreeNodelevel3 = indexMgr.getTStreeNodeByLevel(3, barCheckSAX.Checked);
                }
                else
                {
                    MessageBox.Show("TS-tree is null ! ");
                    return;
                }
            }
            string str = string.Format("R-Tree : \nLevel 1:{0}\nLevel 2:{1}\nLevel 3:{2}\nTS-Tree:\nLevel 1:{3}\nLevel 2:{4}\nLevel 3:{5}", RTreeNodelevel1, RTreeNodelevel2, RTreeNodelevel3, TSTreeNodelevel1, TSTreeNodelevel2, TSTreeNodelevel3);
            MessageBox.Show(str);
        }

        #endregion

        
    }
}
